//// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
//package com.linqingying.gitcode.pullrequest.ui.diff
//
//import com.intellij.collaboration.async.combineState
//import com.intellij.collaboration.async.computationState
//import com.intellij.collaboration.async.mapNullableScoped
//import com.intellij.collaboration.async.stateInNow
//import com.intellij.collaboration.ui.codereview.diff.CodeReviewDiffRequestProducer
//import com.intellij.collaboration.ui.codereview.diff.DiscussionsViewOption
//import com.intellij.collaboration.ui.codereview.diff.model.CodeReviewDiffViewModelComputer
//import com.intellij.collaboration.ui.codereview.diff.model.CodeReviewDiscussionsViewModel
//import com.intellij.collaboration.ui.codereview.diff.model.ComputedDiffViewModel
//import com.intellij.collaboration.ui.codereview.diff.model.DiffProducersViewModel
//import com.intellij.collaboration.ui.codereview.diff.viewer.buildChangeContext
//import com.intellij.collaboration.util.ChangesSelection
//import com.intellij.collaboration.util.ComputedResult
//import com.intellij.collaboration.util.RefComparisonChange
//import com.intellij.collaboration.util.getOrNull
//import com.intellij.openapi.actionSystem.DataKey
//import com.intellij.openapi.project.Project
//import com.intellij.openapi.util.Key
//import com.intellij.openapi.vcs.changes.actions.diff.ChangeDiffRequestProducer
//import com.intellij.platform.util.coroutines.childScope
//import git4idea.changes.GitBranchComparisonResult
//import git4idea.changes.GitTextFilePatchWithHistory
//import git4idea.changes.createVcsChange
//import git4idea.changes.getDiffComputer
//import kotlinx.coroutines.CoroutineName
//import kotlinx.coroutines.CoroutineScope
//import kotlinx.coroutines.ExperimentalCoroutinesApi
//import kotlinx.coroutines.flow.*
//import com.linqingying.gitcode.api.data.pullrequest.GCPullRequestReviewThread
//import com.linqingying.gitcode.pullrequest.data.GCPRDataContext
//import com.linqingying.gitcode.pullrequest.data.provider.GCPRDataProvider
//import com.linqingying.gitcode.pullrequest.data.provider.createThreadsRequestsFlow
//import com.linqingying.gitcode.pullrequest.data.provider.fetchedChangesFlow
//import com.linqingying.gitcode.pullrequest.ui.comment.GCPRThreadsViewModels
//import com.linqingying.gitcode.pullrequest.ui.review.DelegatingGCPRReviewViewModel
//import com.linqingying.gitcode.pullrequest.ui.review.GCPRReviewViewModel
//import com.linqingying.gitcode.pullrequest.ui.review.GCPRReviewViewModelHelper
//
//interface GCPRDiffViewModel : ComputedDiffViewModel, CodeReviewDiscussionsViewModel {
//  val reviewVm: GCPRReviewViewModel
//  val isLoadingReviewData: StateFlow<Boolean>
//
//  fun getViewModelFor(change: RefComparisonChange): Flow<GCPRDiffChangeViewModel?>
//
//  fun reloadReview()
//
//  suspend fun showDiffFor(changes: ChangesSelection)
//
//  companion object {
//    val KEY: Key<GCPRDiffViewModel> = Key.create("GitCode.PullRequest.Diff.ViewModel")
//    val DATA_KEY: DataKey<GCPRDiffViewModel> = DataKey.create(KEY.toString())
//  }
//}
//
//internal class GCPRDiffViewModelImpl(
//  private val project: Project,
//  parentCs: CoroutineScope,
//  private val dataContext: GCPRDataContext,
//  private val dataProvider: GCPRDataProvider,
//  reviewVmHelper: GCPRReviewViewModelHelper,
//  private val threadsVms: GCPRThreadsViewModels,
//) : GCPRDiffViewModel {
//  private val cs = parentCs.childScope(CoroutineName("GitCode Pull Request Diff View Model"))
//  private val reviewDataProvider = dataProvider.reviewData
//
//  override val reviewVm = DelegatingGCPRReviewViewModel(reviewVmHelper)
//
//  private val changesFetchFlow = dataProvider.changesData.fetchedChangesFlow().shareIn(cs, SharingStarted.Lazily, 1)
//  private val helper =
//    CodeReviewDiffViewModelComputer(changesFetchFlow) { changesBundle, change ->
//      val changeContext: Map<Key<*>, Any> = change.buildChangeContext()
//      val changeDiffProducer = ChangeDiffRequestProducer.create(project, change.createVcsChange(project), changeContext)
//                               ?: error("Could not create diff producer from $change")
//      CodeReviewDiffRequestProducer(project, change, changeDiffProducer, changesBundle.patchesByChange[change]?.getDiffComputer())
//    }
//
//  private val changeVmsMap = mutableMapOf<RefComparisonChange, StateFlow<GCPRDiffChangeViewModelImpl?>>()
//
//  private val threads: StateFlow<ComputedResult<List<GCPullRequestReviewThread>>> =
//    reviewDataProvider.createThreadsRequestsFlow().computationState().stateInNow(cs, ComputedResult.loading())
//
//  private val _discussionsViewOption: MutableStateFlow<DiscussionsViewOption> = MutableStateFlow(DiscussionsViewOption.UNRESOLVED_ONLY)
//  override val discussionsViewOption: StateFlow<DiscussionsViewOption> = _discussionsViewOption.asStateFlow()
//
//  override val isLoadingReviewData: StateFlow<Boolean> = reviewVm.pendingReview.combineState(threads) { reviewResult, threadsResult ->
//    reviewResult.isInProgress || threadsResult.isInProgress
//  }
//
//  init {
//    dataProvider.changesData.loadChanges()
//  }
//
//  override fun reloadReview() {
//    reviewDataProvider.resetPendingReview()
//    reviewDataProvider.resetReviewThreads()
//  }
//
//  override val diffVm: StateFlow<ComputedResult<DiffProducersViewModel?>> =
//    helper.diffVm.stateIn(cs, SharingStarted.Eagerly, ComputedResult.loading())
//
//  @OptIn(ExperimentalCoroutinesApi::class)
//  override fun getViewModelFor(change: RefComparisonChange): StateFlow<GCPRDiffChangeViewModelImpl?> =
//    changeVmsMap.getOrPut(change) {
//      changesFetchFlow.computationState().transformLatest {
//        val result = it.getOrNull<GitBranchComparisonResult>() ?: return@transformLatest
//        this.emit(result.patchesByChange[change])
//      }.mapNullableScoped { createChangeVm(change, it) }.stateIn(cs, SharingStarted.Lazily, null)
//    }
//
//  override suspend fun showDiffFor(changes: ChangesSelection) {
//    helper.showChanges(changes)
//  }
//
//  override fun setDiscussionsViewOption(viewOption: DiscussionsViewOption) {
//    _discussionsViewOption.value = viewOption
//  }
//
//  private fun CoroutineScope.createChangeVm(change: RefComparisonChange, diffData: GitTextFilePatchWithHistory) =
//    GCPRDiffChangeViewModelImpl(this, dataContext, dataProvider, change, diffData, threadsVms, discussionsViewOption)
//}
